/*
 * Copyright (c) 2011, Nikolaus Moll
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 * * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * * Neither the name of the gradecalculator.net nor the
 * names of its contributors may be used to endorse or promote products
 * derived from this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
 * DAMAGE.
 */
package net.gradecalculator.plugin.core.factory.impl;

import java.util.LinkedList;
import java.util.List;

import net.gradecalculator.core.interfaces.IElectiveModulesArea;
import net.gradecalculator.core.interfaces.IModuleList;
import net.gradecalculator.core.interfaces.IRegulationsItem;

public class CoreElectiveModulesArea extends AbstractCoreRegulationsItem implements IElectiveModulesArea {
	private int pickCount;
	private float moduleListECTS;
	private int moduleHoursPerWeek;
	private int gradedCount = 0;

	@Override
	public int getPickCount() {
		return pickCount;
	}

	@Override
	public void setPickCount(final int pickCount) {
		this.pickCount = pickCount;
	}

	@Override
	public float getModuleListECTS() {
		return moduleListECTS;
	}

	@Override
	public void setModuleListECTS(final float ects) {
		this.moduleListECTS = ects;
	}

	@Override
	public List<IModuleList> getModuleLists() {
		final List<IModuleList> result = new LinkedList<IModuleList>();
		for (final IRegulationsItem item : getChildren()) {
			result.add((IModuleList) item);
		}
		return result;
	}

	@Override
	public void setModuleLists(final List<IModuleList> moduleLists) {
		final List<IRegulationsItem> children = new LinkedList<IRegulationsItem>();
		for (final IModuleList item : moduleLists) {
			children.add(item);
		}
		setChildren(children);
	}

	@Override
	public void insertModuleList(final IModuleList moduleList, final IModuleList moduleListBefore) {
		insertChild(moduleList, moduleListBefore);
	}

	@Override
	public float getECTS() {
		update();
		return pickCount * moduleListECTS;
	}

	@Override
	public int getHoursPerWeek() {
		update();
		return pickCount * moduleHoursPerWeek;
	}

	@Override
	public void addModuleList(final IModuleList moduleList) {
		addChild(moduleList);
	}

	@Override
	public void removeModuleList(final IModuleList moduleList) {
		removeChild(moduleList);
	}

	@Override
	public void addChild(final IRegulationsItem moduleList) {
		super.addChild(moduleList);
		if (moduleList.isGraded()) {
			gradedCount--;
		}
		update();
	}

	@Override
	public void removeChild(final IRegulationsItem moduleList) {
		super.removeChild(moduleList);
		if (moduleList.isGraded()) {
			gradedCount--;
		}
		update();
	}

	@Override
	public boolean isAddable(final IRegulationsItem item) {
		return (item instanceof IModuleList);
	}

	protected void update() {
		final List<IModuleList> moduleLists = getModuleLists();

		float lastModuleECTS = -1;
		for (final IModuleList list : moduleLists) {
			if (lastModuleECTS < 0) {
				lastModuleECTS = list.getECTS();
				continue;
			}
			if (lastModuleECTS != list.getECTS()) {
				lastModuleECTS = 0;
				break;
			}
		}

		int lastModuleHoursPerWeek = -1;
		for (final IModuleList list : moduleLists) {
			if (lastModuleHoursPerWeek < 0) {
				lastModuleHoursPerWeek = list.getHoursPerWeek();
				continue;
			}
			if (lastModuleHoursPerWeek != list.getHoursPerWeek()) {
				lastModuleHoursPerWeek = 0;
				break;
			}
		}

		moduleListECTS = Math.max(lastModuleECTS, 0);
		moduleHoursPerWeek = Math.max(lastModuleHoursPerWeek, 0);
	}

	@Override
	public boolean isGraded() {
		return (gradedCount > 0);
	}

}
